package com.ruoyi.common.utils;

import org.junit.Test;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;

public class PartUtil {
    //需转换的数字

    private double number;

    //中文数字
    private String[] source1 = {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};

    //数字单位
    private String[] source2 = {"仟","佰","拾","亿","仟","佰","拾","万","仟","佰","拾","元","角","分"};

    /**
     * 单位进位，中文默认为4位即（万、亿）
     */
    public static  int UNIT_STEP = 4;

    /**
     * 单位
     */
    public static String[] CN_UNITS = new String[] { "个", "十", "百", "千", "万", "十",
            "百", "千", "亿", "十", "百", "千", "万" };

    /**
     * 汉字
     */
    public static String[] CN_CHARS = new String[] { "零", "一", "二", "三", "四",
            "五", "六", "七", "八", "九" };

    //构造函数
    public PartUtil(double number) {
        this.number = number;
    }
    //构造函数
    public PartUtil() {
    }
    //转换整数部分
    private String integerToChinese(){
        //整数部分
        long integerPart = (long)number;
        //将整数部分转换成字符串
        String integerStr = Long.toString(integerPart);
        //取得整数部分的长度
        int intPartLen = integerStr.length();
        //将整数部分转换成字符数组
        char[] intChars = integerStr.toCharArray();
        //当前字符是否为零的标志变量
        boolean bitState = false;
        //转换结果
        String convertResult = null;
        //当整数部分为0时
        if (intChars[0] == '0'){
            return "";
        }
        //当整数部分的长度为1时
        if (intPartLen == 1){
            convertResult = source1[intChars[0] - 48] + source2[11];
            return convertResult;
        }else{
        //char类型不能直接转换成int，由于数字char类型，与整型正好相差48，则能通过char-48转换成整型。

        //循环处理每一个数字，index用于intChars定位，position用于source2定位
            for (int index = 0 , position = source2.length - intPartLen - 2; index < intChars.length; index++,position++){
                //判断当前数字是否为零，将设置bitState,为零时为true,否则false
                if (intChars[index] == '0'){
                    bitState = true;
                }else{
                    bitState = false;
                }
                //处理第一个数
                if (index == 0){
                    convertResult = source1[intChars[0] - 48] + source2[position];
                    //处理最后一个数字，当最后一个数字为零时
                }else if (index == intChars.length -1 && intChars[index] == '0'){
                    //将已有的转换结果，转换成字符数组并判断最后一个字符是否零，
                    //如果是零，则去掉最后一个零，加上单位元
                    char[] temporaryChars = convertResult.toCharArray();
                    if (temporaryChars[temporaryChars.length-1] == '零'){
                        convertResult = convertResult.substring(0,convertResult.length()-1);
                    }
                    convertResult += "元";
                    break;
                    //处理最后一个数字，当最后一个数字不为零时
                }else if (index == intChars.length -1 && intChars[index] != '0') {
                    //直接取中文数字，加上单位元
                    convertResult += source1[intChars[index] - 48] + "元";
                    break;
                    //处理中间数字,这部分是转换最难的部分
                    //先分别处理在亿、万位时如何转换
                }else{
                    //当前处于亿位时，并且当前字符是0时
                    if (source2[position] == "亿" && bitState){
                        //将已有的转换结果，转换成字符数组并判断最后一个字符是否零
                        //如果是零，则去掉最后一个零，加上单位亿
                        char[] temporaryChars = convertResult.toCharArray();
                        if (temporaryChars[temporaryChars.length-1] == '零'){
                            convertResult = convertResult.substring(0,convertResult.length()-1);
                            continue;
                        }
                        convertResult += "亿";
                        //当前处于亿位时，并且当前字符不是0时
                    }else if (source2[position] == "亿" && !bitState) {
                        //直接取中文数字，加上单位元
                        convertResult += source1[intChars[index] - 48] + source2[position];
                    //当前处于万位时，并且当前字符是0时
                    }else if (source2[position] == "万" && bitState){
                    //将已有的转换结果，转换成字符数组并判断最后一个字符是否零，
                    //如果是零，则去掉最后一个零，并且去掉零，如果最后一个字符是亿，则不加万单位
                    //否则要加
                        char[] temporaryChars = convertResult.toCharArray();
                        if (temporaryChars[temporaryChars.length-1] == '零') {
                            convertResult = convertResult.substring(0,convertResult.length()-1);
                            if (convertResult.toCharArray()[convertResult.length()-1] == '亿') {
                                continue;
                            }
                        }
                        convertResult += "万";
                    //当前处于万位时，并且当前字符不是0时
                    }else if (source2[position] == "万" && !bitState){
                        //直接取中文数字，加上单位元
                        convertResult += source1[intChars[index] - 48] + source2[position];
                    //处理不在亿、万位的数字转换
                    }else {
                        //当前字符不是0时
                        if (!bitState){
                            //直接取中文数字，根据当前位置取数字单位
                            convertResult += source1[intChars[index] - 48] + source2[position];
                            continue;
                        //当前字符是0时
                        }else {
                            //将已有的转换结果，转换成字符数组并判断最后一个字符是否零，
                            //如果是零，不转换当前字符，如果不是零时，进行转换不带数字单位
                            char[] temporaryChars = convertResult.toCharArray();
                            if (temporaryChars[temporaryChars.length-1] == '零'){
                                continue;
                            }
                            convertResult += source1[0];
                        }
                    }
                }
            }

            //返回最终整数部分转换结果
            return convertResult;
        }
    }

    /**算法：1.通过long强制转换，取得整数部分integerPart

     2.通过number-integerPart取得小数部分decimalPart，decimalPart * 100用于保留两位

     小数，由于计算处理double精度问题，用math.round函数圆整。小数部分可以出0，1,12,50

     */

    //转换小数部分
    private String decimalToChinese(){
        //小数部分
        int decimalPart = (int)Math.round((number - (long)number) * 100);
        //将小数部分转换成字符串.
        String decimalStr = Integer.toString(decimalPart);
        //转换结果
        String result;
        //将小数部分转换成字符数组
        char[] decimalChars = decimalStr.toCharArray();
        //取得char[]长度
        int charLen = decimalChars.length;
        //当charLen只有1位时，且当前char为0直接返回空字符串
        if (charLen == 1 && decimalChars[0] == '0'){
            return "";
         //   当charLen只有1位时，且当前char不为0，转换成零加当前字符的中文数字
        }else if (charLen == 1 && decimalChars[0] != '0'){
            result = "零" + source1[decimalChars[0] - 48] + source2[13];
            //当charLen为2位时，且最后一位字符为0
        }else if (decimalChars[1] != '0'){
            result = source1[decimalChars[0] - 48] + source2[12]  +  source1[decimalChars[1]- 48] + source2[13];
        //除上述条件，其它情况的转换
        }else{
            result = source1[decimalChars[0] - 48] + source2[12];
        }
        return result;
    }

    /**

     *转换方法

     *@return String

     */
    //外部接口
    public String convertToChinese(){
        return integerToChinese() + decimalToChinese();
    }





    /**
     * 将阿拉伯数字转换为中文数字123=》一二三
     *
     * @param srcNum
     * @return
     */
    public static String getCNNum(int srcNum) {
        String desCNNum = "";

        if (srcNum <= 0)
            desCNNum = "零";
        else {
            int singleDigit;
            while (srcNum > 0) {
                singleDigit = srcNum % 10;
                desCNNum = String.valueOf(CN_CHARS[singleDigit]) + desCNNum;
                srcNum /= 10;
            }
        }

        return desCNNum;
    }

    /**
     * 数值转换为中文字符串 如2转化为贰
     */
    public String cvt(long num) {
        return this.cvt(num, false);
    }

    /**
     * 数值转换为中文字符串(口语化)
     *
     * @param num
     *            需要转换的数值
     * @param isColloquial
     *            是否口语化。例如12转换为'十二'而不是'一十二'。
     * @return
     */
    public  String cvt(String num, boolean isColloquial) {
        int integer, decimal;
        StringBuffer strs = new StringBuffer(32);
        String[] splitNum = num.split("\\.");
        integer = Integer.parseInt(splitNum[0]);    //整数部分
        decimal = Integer.parseInt(splitNum[1]);    //小数部分
        String[] result_1 =convert(integer, isColloquial);
        for (String str1 : result_1)
            strs.append(str1);
        if(decimal==0){//小数部分为0时
            return strs.toString();
        }else{
            String result_2 =getCNNum(decimal);  //例如5.32，小数部分展示三二，而不是三十二
            strs.append("点");
            strs.append(result_2);
            return strs.toString();
        }
    }

    /*
     * 对于int,long类型的数据处理
     */
    public String cvt(long num, boolean isColloquial) {
        String[] result = this.convert(num, isColloquial);
        StringBuffer strs = new StringBuffer(32);
        for (String str : result) {
            strs.append(str);
        }
        return strs.toString();
    }

    /**
     * 将数值转换为中文
     *
     * @param num
     *            需要转换的数值
     * @param isColloquial
     *            是否口语化。例如12转换为'十二'而不是'一十二'。
     * @return
     */
    public  String[] convert(long num, boolean isColloquial) {
        if (num < 10) {// 10以下直接返回对应汉字
            return new String[] { CN_CHARS[(int) num] };// ASCII2int
        }

        char[] chars = String.valueOf(num).toCharArray();
        if (chars.length > CN_UNITS.length) {// 超过单位表示范围的返回空
            return new String[] {};
        }

        boolean isLastUnitStep = false;// 记录上次单位进位
        ArrayList<String> cnchars = new ArrayList<String>(chars.length * 2);// 创建数组，将数字填入单位对应的位置
        for (int pos = chars.length - 1; pos >= 0; pos--) {// 从低位向高位循环
            char ch = chars[pos];
            String cnChar = CN_CHARS[ch - '0'];// ascii2int 汉字
            int unitPos = chars.length - pos - 1;// 对应的单位坐标
            String cnUnit = CN_UNITS[unitPos];// 单位
            boolean isZero = (ch == '0');// 是否为0
            boolean isZeroLow = (pos + 1 < chars.length && chars[pos + 1] == '0');// 是否低位为0

            boolean isUnitStep = (unitPos >= UNIT_STEP && (unitPos % UNIT_STEP == 0));// 当前位是否需要单位进位

            if (isUnitStep && isLastUnitStep) {// 去除相邻的上一个单位进位
                int size = cnchars.size();
                cnchars.remove(size - 1);
                if (!CN_CHARS[0].equals(cnchars.get(size - 2))) {// 补0
                    cnchars.add(CN_CHARS[0]);
                }
            }

            if (isUnitStep || !isZero) {// 单位进位(万、亿)，或者非0时加上单位
                cnchars.add(cnUnit);
                isLastUnitStep = isUnitStep;
            }
            if (isZero && (isZeroLow || isUnitStep)) {// 当前位为0低位为0，或者当前位为0并且为单位进位时进行省略
                continue;
            }
            cnchars.add(cnChar);
            isLastUnitStep = false;
        }

        Collections.reverse(cnchars);
        // 清除最后一位的0
        int chSize = cnchars.size();
        String chEnd = cnchars.get(chSize - 1);
        if (CN_CHARS[0].equals(chEnd) || CN_UNITS[0].equals(chEnd)) {
            cnchars.remove(chSize - 1);
        }

        // 口语化处理
        if (isColloquial) {
            String chFirst = cnchars.get(0);
            String chSecond = cnchars.get(1);
            if (chFirst.equals(CN_CHARS[1]) && chSecond.startsWith(CN_UNITS[1])) {// 是否以'一'开头，紧跟'十'
                cnchars.remove(0);
            }
        }
        return cnchars.toArray(new String[] {});
    }

    public static void main(String[] args) {
        PartUtil temp = new PartUtil();
        String i ="40.3";
        int t = 2234;
        double j = 221.23;
        System.out.println(temp.cvt(i,true));//四十点三
        System.out.println(temp.cvt(t,true));//二千二百三十四
        System.out.println(temp.cvt(""+j,true));//二百二十一点二三
    }

    //  传入单位是万   自动万，亿
    public static String formatUnitDouble(double d,int sum) {

        String value = formatDouble(d,sum);
        StringTokenizer stringTokenizer = new StringTokenizer(value,".");
        String value1 = stringTokenizer.nextToken();
        if(value1.length()<5){
            return  value+"万";
        }else{
            return  formatDouble(Double.valueOf(value)*0.0001,sum)+"亿";
        }
    }
    //传入单位是个 自动万，亿
    public static String formatUnitDouble2(double d,int sum) {
        String value = formatDouble(d,sum);
        StringTokenizer stringTokenizer = new StringTokenizer(value,".");
        String value1 = stringTokenizer.nextToken();
        if(value1.length()<=4){
            return  value;
        }else if(value1.length()<=8 && value1.length()>=5){
            return  formatDouble(Double.valueOf(value)*0.0001,sum)+"万";
        }else if(value1.length()<=12 && value1.length()>=9){
            return  formatDouble(Double.valueOf(value)*0.00000001,sum)+"亿";
        }else{
            return  formatDouble(Double.valueOf(value)*0.000000000001,sum)+"万亿";
        }
    }
    //double类型如果小数点后为零则显示整数否则保留两位小数
    public static String formatDouble(double d,int sum) {
        BigDecimal bg = new BigDecimal(d).setScale(sum, RoundingMode.UP);
        double num = bg.doubleValue();
        if (Math.round(num) - num == 0) {
            return String.valueOf((long) num);
        }
        return String.valueOf(num);
    }

    public static Double formatDouble2(double value,int sum) {
        return Double.valueOf(formatDouble(value,sum));
    }
    /**
     * 将数值转换为中文
     *
     * @param value 需要转换的数值
     * @param sum 保留几位小数
     * @return String
     */
    public static String format5(double value,int sum) {
        return String.format("%."+sum+"f", value);
    }


    @Test
    public static void main111(String[] args){
        PartUtil conver = new PartUtil(1010101010.12);
        System.out.println(conver.convertToChinese());
    }

}
